package org.dftproject.genesis.ui.presentation;

import org.dftproject.genesis.ui.actions.NewTabAction;
import org.dftproject.genesis.ui.presentation.tabcontrol.ITabControlListener;
import org.dftproject.genesis.ui.presentation.tabcontrol.TabItem;
import org.dftproject.genesis.ui.presentation.tabcontrol.TabControl;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.StackDropResult;
import org.eclipse.ui.presentations.StackPresentation;

public class TabControlPresentation extends StackPresentation {

	private static final String DATAKEY_PART = "IPresentablePart";

	private final Composite parent;
	private final TabControl tabControl;

	protected TabControlPresentation(Composite parent, IStackPresentationSite stackSite) {
		super(stackSite);
		this.parent = parent;

		tabControl = new TabControl(parent, SWT.NONE);
		tabControl.addTabControlListener(new ITabControlListener() {

			public void newTab() {
				createNewTab();
			}

			public void tabSelected(TabItem item) {
				getSite().selectPart((IPresentablePart) item.getData(DATAKEY_PART));
			}

			public void tabClosed(TabItem item) {
				getSite().close(new IPresentablePart[] { (IPresentablePart) item.getData(DATAKEY_PART) });
			}

		});

		Menu contextMenu = new Menu(tabControl);

		MenuItem newTab = new MenuItem(contextMenu, SWT.NONE);
		newTab.setText("New Tab");
		newTab.addListener(SWT.Selection, new Listener() {
			
			public void handleEvent(Event event) {
				createNewTab();
			}
			
		});
		
		new MenuItem(contextMenu, SWT.BAR);
		
		final MenuItem closeOthers = new MenuItem(contextMenu, SWT.NONE);
		closeOthers.setText("Close Other Tabs");
		closeOthers.addListener(SWT.Selection, new Listener() {
			
			public void handleEvent(Event event) {
				IPresentablePart part = getSite().getSelectedPart();
				if (part == null)
					return;

				IPresentablePart[] parts = getSite().getPartList();
				if (parts.length < 2)
					return;

				IPresentablePart[] closeParts = new IPresentablePart[parts.length - 1];

				int j = 0;
				for (int i = 0; i < parts.length; i++) {
					if (parts[i] != part) {
						closeParts[j] = parts[i];
						j++;
					}
				}

				getSite().close(closeParts);
			}
			
		});
		
		final MenuItem close = new MenuItem(contextMenu, SWT.NONE);
		close.setText("Close Tab");
		close.addListener(SWT.Selection, new Listener() {
			
			public void handleEvent(Event event) {
				IPresentablePart part = getSite().getSelectedPart();
				if (part == null)
					return;
				getSite().close(new IPresentablePart[] { part });
			}
			
		});
		
		contextMenu.addMenuListener(new MenuListener() {

			public void menuHidden(MenuEvent e) {
			}

			public void menuShown(MenuEvent e) {
				close.setEnabled(getSite().getPartList().length > 1);
				closeOthers.setEnabled(getSite().getPartList().length > 1);
			}
			
		});

		tabControl.setMenu(contextMenu);
	}

	protected void createNewTab() {
		IWorkbench workbench = PlatformUI.getWorkbench();
		IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
		ICommandService commandService = (ICommandService) window.getService(ICommandService.class);
		Command command = commandService.getCommand(NewTabAction.ID);
		try {
			command.executeWithChecks(new ExecutionEvent());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void addPart(final IPresentablePart newPart, Object cookie) {
		final TabItem item = new TabItem(tabControl, SWT.NONE);
		item.setData(DATAKEY_PART, newPart);

		updateItem(newPart);

		newPart.addPropertyListener(new IPropertyListener() {

			public void propertyChanged(Object source, int propId) {
				updateItem(newPart);
			}

		});
	}

	protected void updateItem(final IPresentablePart part) {
		TabItem item = getTabItem(part);
		if (item == null)
			return;

		item.setText(part.getName());
		item.setImage(part.getTitleImage());

		resizeSelectedPart();
	}

	@Override
	public void dispose() {
		tabControl.dispose();
	}

	@Override
	public StackDropResult dragOver(Control currentControl, Point location) {
		return null;
	}

	@Override
	public Control getControl() {
		return tabControl;
	}

	@Override
	public Control[] getTabList(IPresentablePart part) {
		return null;
	}

	@Override
	public void removePart(IPresentablePart oldPart) {
		tabControl.closeTabItem(getTabItem(oldPart));
		resizeSelectedPart();
	}

	protected TabItem getTabItem(IPresentablePart part) {
		for (TabItem item : tabControl.getTabItems()) {
			if (item.getData(DATAKEY_PART) == part) {
				return item;
			}
		}
		return null;
	}

	@Override
	public void selectPart(IPresentablePart toSelect) {
		tabControl.setSelection(getTabItem(toSelect));

		for (IPresentablePart part : getSite().getPartList())
			part.setVisible(part == toSelect);

		resizeSelectedPart();
	}

	@Override
	public void setActive(int newState) {
	}

	@Override
	public void setBounds(Rectangle bounds) {
		tabControl.setBounds(bounds);
		resizeSelectedPart();
	}

	protected void resizeSelectedPart() {
		IPresentablePart part = getSite().getSelectedPart();
		if (part == null)
			return;

		TabItem item = getTabItem(part);
		if (item == null)
			return;

		Rectangle bounds = tabControl.getClientArea();

		bounds = item.getDisplay().map(tabControl, parent, bounds);

		part.setBounds(bounds);
	}

	@Override
	public void setState(int state) {
	}

	@Override
	public void setVisible(boolean isVisible) {
		tabControl.setVisible(isVisible);
		if (getSite().getSelectedPart() == null)
			return;
		getSite().getSelectedPart().setVisible(isVisible);
		if (getSite().getSelectedPart().getToolBar() != null)
			getSite().getSelectedPart().getToolBar().setVisible(isVisible);
	}

	@Override
	public void showPaneMenu() {
	}

	@Override
	public void showSystemMenu() {
	}

}
